/* Copyright (c) 2009-2010, Sean A.O. Harney <sharney3@gmail.com> */

#ifndef FUZZER_EXPR_H
#define FUZZER_EXPR_H

typedef enum {
    EXPR_LEAF,
    EXPR_BINARY,
    EXPR_ASSIGNMENT,
    EXPR_FUNCTIONCALL
} EXPR_TYPE;

typedef enum {
    BINARY_OP_ADD,
    BINARY_OP_SUBTRACT,
    BINARY_OP_MULTIPLY,
    BINARY_OP_DIVIDE,
    BINARY_OP_EQUALITY,
    BINARY_OP_LIST_CONS
} BINARY_OP_TYPE;

typedef enum {
    LEAF_INT,
    LEAF_FLOAT,
    LEAF_STRING,
    LEAF_BOOL,
    LEAF_ID,			//func or var id
    LEAF_LIST
} LEAF_TYPE;			//leaf in expr tree

typedef struct st_expr *EXPR_P;

struct st_leaf {
    LEAF_TYPE type;
    union {
	int int_val;		/*for both PINT and NINT */
	float float_val;
	char *string_val;
	bool bool_val;
	char *id_val;		//a symname (varname) for leaf_id, lexically a TOK_ID or TOK_DOLLARID
	LLIST_P list_val;	// list of EXPR_P or NULL for empty
    } val;
};

struct st_functioncall {
    char *funcname;
    LLIST_P args_expr_list;	//llist of EXPR_P
};


struct st_expr {
    EXPR_TYPE type;

    union {
	struct st_leaf leaf;	// lhs,rhs = NULL

	union {
	    BINARY_OP_TYPE op;	// one of + - \ * TOK_'s
	} binary_op;

	//No need for union member type=assignment, only uses lhs,rhs

	struct st_functioncall functioncall;	//type=EXPR_FUNCTIONCALL
    } u;

    EXPR_P lhs, rhs;
};


/* prototypes */
char *leaf_val_to_str(EXPR_P expr);
char *expr_type_to_str(EXPR_TYPE type);
char *leaf_type_to_str(LEAF_TYPE type);
char *binary_op_type_to_str(BINARY_OP_TYPE type);


EXPR_P new_expr_leaf_int(int val);	/* for both PINT and NINT */
EXPR_P new_expr_leaf_float(float val);
EXPR_P new_expr_leaf_string(char *val);
EXPR_P new_expr_leaf_bool(bool val);
EXPR_P new_expr_leaf_id(char *id);
EXPR_P new_expr_leaf_list(LLIST_P list);
EXPR_P new_expr_binary(BINARY_OP_TYPE op, EXPR_P lhs, EXPR_P rhs);
EXPR_P new_expr_assignment(EXPR_P lhs, EXPR_P rhs);
EXPR_P new_expr_functioncall(char *funcname, LLIST_P args_leafexpr_list);

#endif				/* FUZZER_EXPR_H */
